<!--
 * Tencent is pleased to support the open source community by making BK-JOB生物智算平台 available.
 *
 * Copyright (C) 2021 THL A29 Limited, a Tencent company.  All rights reserved.
 *
 * BK-JOB生物智算平台 is licensed under the MIT License.
 *
 * License for BK-JOB生物智算平台:
 *
 *
 * Terms of the MIT License:
 * ---------------------------------------------------
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
 * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
 * the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
-->

<template>
  <div id="templateVariableRender">
    <div v-if="showEmpty">
      --
    </div>
    <template v-else>
      <div class="variable-batch-action">
        <bk-button
          v-if="isOperation"
          text
          @click="handleShowBatchOperation">
          <icon type="bulk-edit" />
          {{ $t('template.批量编辑') }}
        </bk-button>
        <bk-button
          v-if="isEditOfPlan"
          text
          @click="handleShowBatchEditOfPlan">
          <icon type="bulk-edit" />
          {{ $t('template.批量编辑变量值') }}
        </bk-button>
      </div>
      <div class="task-global-variable-box">
        <template v-for="(item, index) in variable">
          <div
            v-if="item.delete !== 1"
            :key="`${item.name}_${index}`"
            class="render-global-variable"
            :class="[
              {
                'step-mode-diff': isDiff,
              },
              isSelect ?
                selectValue.includes(item.name) ? 'selected' : 'not-selected'
                : '',
            ]">
            <div
              class="global-variable-content"
              :class="[diff[item.id] && diff[item.id].type]"
              @click="handlerOperation(item, index)"
              @mouseenter="handleShowPopoverDetail(item)"
              @mouseleave="handleHidePopoverDetail">
              <div
                :id="`globalVariableWithName_${item.name}`"
                class="variable-type">
                <icon :type="item.icon" />
              </div>
              <div class="variable-info">
                <div class="variable-name">
                  {{ item.name }}
                </div>
                <div class="variable-description">
                  {{ item.valueText }}
                </div>
              </div>
              <icon
                v-if="isOperation"
                class="variable-delete-btn"
                type="close"
                @click.stop="handleDelete(index)" />
            </div>
          </div>
        </template>
        <div
          v-if="isOperation"
          key="create"
          class="global-variable-new">
          <div
            v-test="{ type: 'button', value: 'create_global_variable' }"
            class="new-btn"
            @click="handleCreate">
            <icon
              class="create-flag"
              type="plus" />
            <span>{{ $t('template.全局变量.label') }}</span>
          </div>
          <div
            v-bk-tooltips="$t('template.使用指引')"
            class="use-guide"
            :class="{
              active: isShowUseGuide,
            }"
            @click.stop="handleUseGuideToggle">
            <icon type="help-document-fill" />
          </div>
        </div>
      </div>
      <popover-detail
        v-if="currentPopoverDetail.name"
        :data="currentPopoverDetail"
        :default-field="defaultField"
        :edit-of-plan="isEditOfPlan"
        :select-value="selectValue" />
      <element-teleport
        v-if="isOperation && isShowUseGuide"
        target="#globalVariableGuide">
        <variable-use-guide
          @on-close="handleUseGuideClose" />
      </element-teleport>
      <jb-sideslider
        v-if="isView || isEditOfPlan"
        ref="variableView"
        :is-show.sync="isShowDetail"
        :media="detailMedia"
        :show-footer="false"
        :title="$t('template.查看全局变量')">
        <detail
          v-if="isShowDetail"
          :data="currentData"
          :default-field="defaultField" />
      </jb-sideslider>
      <jb-sideslider
        v-if="isEditOfPlan"
        :is-show.sync="isShowEditOfPlan"
        :title="$t('template.编辑全局变量')"
        :width="960">
        <edit-of-plan
          v-if="isShowEditOfPlan"
          ref="planGlobalVar"
          :data="currentData"
          @on-change="handlePlanEditSubmit" />
      </jb-sideslider>
      <jb-sideslider
        v-if="isEditOfPlan"
        footer-offset-target="variable-value"
        :is-show.sync="isShowBatchEditOfPlan"
        :ok-text="$t('template.确定')"
        :title="$t('template.批量编辑变量值')"
        :width="960">
        <batch-edit-of-plan
          v-if="isShowBatchEditOfPlan"
          ref="planGlobalVar"
          :selected-list="selectValue"
          :variable-list="variable"
          @on-change="handleBatchPlanEditSubmit" />
      </jb-sideslider>
      <jb-sideslider
        v-if="isOperation"
        :is-show.sync="isShowOperation"
        v-bind="operationSideSliderInfo"
        :width="960">
        <operation
          v-if="isShowOperation"
          ref="globalVar"
          :data="currentData"
          :variable="realVariable"
          @on-change="handleOperationSubmit" />
      </jb-sideslider>
      <jb-sideslider
        v-if="isOperation"
        :is-show.sync="isShowBatchOperation"
        :media="batchOperationMediaQuery"
        :title="$t('template.批量编辑变量')">
        <batch-operation
          v-if="isShowBatchOperation"
          :variable="variable"
          @on-change="handleBatchOperationSubmit" />
      </jb-sideslider>
    </template>
  </div>
</template>
<script>
  import _ from 'lodash';

  import VariableModel from '@model/task/global-variable';

  import I18n from '@/i18n';
  import VariableUseGuide from '@/views/task-manage/common/variable-use-guide';

  import BatchEditOfPlan from './batch-edit-of-plan';
  import BatchOperation from './batch-operation';
  import Detail from './detail';
  import EditOfPlan from './edit-of-plan';
  import Operation from './operation';
  import PopoverDetail from './popover-detail';

  export default {
    name: 'RenderGlobalVar',
    components: {
      VariableUseGuide,
      Operation,
      BatchOperation,
      Detail,
      EditOfPlan,
      BatchEditOfPlan,
      PopoverDetail,
    },
    props: {
      list: {
        type: Array,
        required: true,
      },
      /*
       * @value ''：仅可查看详情
       * @value 'operate': 可编辑可新建可删除
       * @value 'select': 选择模式
       * @value 'editOfPlan'：不可删除，使用执行方案的编辑功能
       * @value 'viewOfPlan': 执行方案的查看功能
       * @value 'diff'：diff场景
       */
      mode: {
        type: String,
        default: '',
      },
      selectValue: {
        type: Array,
        default: () => [],
      },
      defaultField: {
        type: String,
        default: I18n.t('template.初始值'),
      },
      diff: {
        type: Object,
        default: () => ({}),
      },
    },
    data() {
      return {
        isShowDetail: false,
        isShowUseGuide: false,
        isShowOperation: false,
        isShowBatchOperation: false,
        isShowEditOfPlan: false,
        isShowBatchEditOfPlan: false,
        variable: [],
        currentPopoverDetail: {},
        currentData: {},
        currentIndex: -1,
        currentOperation: 'create',
        detailMedia: [],
      };
    },
    computed: {
      /**
       * @desc 展示数据为空时的文本
       * @returns { Boolean }
       */
      showEmpty() {
        if (this.isOperation) {
          return false;
        }
        return this.variable.length < 1;
      },
      /**
       * @desc 新建、编辑全局变量
       * @returns { Boolean }
       */
      isOperation() {
        return this.mode === 'operate';
      },
      /**
       * @desc 选择全局变量
       * @returns { Boolean }
       */
      isSelect() {
        return this.mode === 'select' || this.mode === 'editOfPlan';
      },
      /**
       * @desc 编辑执行方案中的全局变量
       * @returns { Boolean }
       */
      isEditOfPlan() {
        return this.mode === 'editOfPlan';
      },
      /**
       * @desc 查看全局变量
       * @returns { Boolean }
       */
      isView() {
        return !this.mode;
      },
      /**
       * @desc 插卡全局变量同步对比差异
       * @returns { Boolean }
       */
      isDiff() {
        return this.mode === 'diff';
      },
      /**
       * @desc 展示的全局变量不包含已删除
       * @returns { Array }
       */
      realVariable() {
        // 过滤掉已经删除的变量
        const validVariable = this.variable.filter(item => !item.delete);
        // 编辑操作不包含正在编辑的变量
        if (this.currentOperation === 'edit') {
          return validVariable.filter(item => item.name !== this.currentData.name);
        }
        return validVariable;
      },
      /**
       * @desc 变量编辑侧栏的展示信息
       * @returns { Object }
       */
      operationSideSliderInfo() {
        if (Object.keys(this.currentData).length < 1) {
          return {
            title: I18n.t('template.新建全局变量'),
            okText: I18n.t('template.提交'),
          };
        }
        return {
          title: I18n.t('template.编辑全局变量'),
          okText: I18n.t('template.保存'),
        };
      },
    },
    watch: {
      list: {
        handler(value) {
          this.variable = _.cloneDeep(value);
        },
        immediate: true,
      },
    },
    created() {
      this.batchOperationMediaQuery = [1080, 1280, 1520, 1800];
    },
    methods: {
      /**
       * @desc 更新外部数据
       */
      triggerChange() {
        this.$emit('on-change', this.variable);
      },
      /**
       * @desc 显示全局变量详情tips
       * @param {Object} variableInfo 全局变量详情
       */
      handleShowPopoverDetail(variableInfo) {
        this.currentPopoverDetail = variableInfo;
      },
      /**
       * @desc 隐藏全局变量详情tips
       */
      handleHidePopoverDetail() {
        this.currentPopoverDetail = {};
      },
      /**
       * @desc 批量编辑
       */
      handleShowBatchOperation() {
        this.isShowBatchOperation = true;
      },
      /**
       * @desc 批量编辑执行方案中变量值
       */
      handleShowBatchEditOfPlan() {
        this.isShowBatchEditOfPlan = true;
      },
      /**
       * @desc 点击全局变量
       * @param {Object} variableInfo 全局变量详情
       * @param {Index} index 点击变量的索引
       */
      handlerOperation(variableInfo, index) {
        this.currentData = variableInfo;
        if (this.isView) {
          this.detailMedia = variableInfo.type === VariableModel.TYPE_HOST ? [960] : [600, 660, 720, 780];
          this.isShowDetail = true;
          return;
        }
        this.currentOperation = 'edit';
        this.currentIndex = index;
        if (this.isEditOfPlan) {
          this.isShowEditOfPlan = true;
          return;
        }
        this.isShowOperation = true;
      },
      /**
       * @desc 删除全局变量
       * @param {Number} index 删除变量的索引
       */
      handleDelete(index) {
        this.$bkInfo({
          title: I18n.t('template.确定删除该全局变量？'),
          subTitle: I18n.t('template.若该变量被步骤引用，请及时检查并更新步骤设置'),
          confirmFn: () => {
            const currentVar = this.variable[index];
            if (currentVar.id > 0) {
              // 删除已存在的变量
              //  —设置delete
              currentVar.delete = 1;
            } else {
              // 删除新建的变量
              //  —直接删除
              this.variable.splice(index, 1);
            }
            this.triggerChange();
          },
        });
      },
      /**
       * @desc 显示新建全局变量弹层
       */
      handleCreate() {
        this.currentOperation = 'create';
        this.currentData = {};
        this.isShowOperation = true;
        this.$refs.globalVar && this.$refs.globalVar.reset();
      },
      /**
       * @desc 执行方案全局变量编辑
       * @param {Object} payload 全局变量数据
       */
      handlePlanEditSubmit(payload) {
        const variable = new VariableModel(payload);
        this.variable.splice(this.currentIndex, 1, variable);
        this.triggerChange();
      },
      /**
       * @desc 批量编辑执行方案全局变量
       * @param {Array} variableList 全局变量列表
       */
      handleBatchPlanEditSubmit(variableList) {
        const variables = variableList.map(item => new VariableModel(item));
        this.variable = variables;
        this.triggerChange();
      },
      /**
       * @desc 全局变量编辑
       * @param {Object} payload 全局变量数据
       */
      handleOperationSubmit(payload) {
        const payloadModel = new VariableModel(payload);
        if (this.currentOperation === 'create') {
          // 新建变量——追加
          this.variable.push(payloadModel);
        } else {
          // 编辑变量——替换
          this.variable.splice(this.currentIndex, 1, payloadModel);
        }
        this.triggerChange();
        this.currentOperation = '';
      },
      /**
       * @desc 全局变量批量编辑
       * @param {Array} variableList 全局变量数据
       */
      handleBatchOperationSubmit(variableList) {
        this.variable = variableList;
        this.triggerChange();
      },
      handleUseGuideToggle() {
        this.isShowUseGuide = !this.isShowUseGuide;
      },
      handleUseGuideClose() {
        this.isShowUseGuide = false;
      },
    },
  };
</script>
<style lang='postcss' scoped>
  @import url("@/css/mixins/media");

  .task-global-variable-box {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    margin-top: -10px;

    .render-global-variable {
      margin-top: 10px;
      margin-right: 10px;
      cursor: pointer;
      border-color: var(--color-primary);

      &.selected {
        .global-variable-content {
          border-color: var(--color-primary);
        }
      }

      &.not-selected {
        .variable-type {
          background: #dcdee5;
        }
      }
    }

    .global-variable-content {
      position: relative;
      display: flex;
      width: 160px;
      height: 50px;
      padding: 0 10px;
      background: #fff;
      border: 1px solid #c4c6cc;
      border-radius: 2px;
      box-sizing: border-box;
      transition: all 0.15s;
      align-items: center;

      &:hover {
        background: var(--color-primary-hover-light);
        border-color: var(--color-primary);

        .variable-delete-btn {
          opacity: 100%;
          visibility: visible;
          transform: scale(1);
        }
      }
    }

    .variable-type {
      display: flex;
      width: 30px;
      height: 30px;
      font-size: 18px;
      color: #fff;
      background: var(--color-primary);
      border-radius: 2px;
      align-items: center;
      justify-content: center;
      flex: 0 0 30px;
      transition: all 0.15s;
    }

    .variable-delete-btn {
      position: absolute;
      top: -9px;
      right: -9px;
      width: 18px;
      height: 18px;
      font-size: 14px;
      line-height: 18px;
      color: #fff;
      cursor: pointer;
      background: #c4c6cc;
      border-radius: 50%;
      opacity: 0%;
      visibility: hidden;
      transform: scale(0.8);
      transition: all 0.25s;
    }

    .variable-info {
      display: flex;
      padding-left: 10px;
      font-size: 12px;
      line-height: 1;
      color: #979ba5;
      flex-direction: column;

      .variable-name {
        height: 16px;
        max-width: 100px;
        margin-bottom: 2px;
        overflow: hidden;
        font-size: 14px;
        color: #63656e;
        text-overflow: ellipsis;
        white-space: nowrap;
      }

      .variable-description {
        height: 14px;
        max-width: 138px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
    }

    .global-variable-new {
      position: relative;
      width: 160px;
      margin-top: 10px;

      .new-btn,
      .use-guide {
        cursor: pointer;

        &:hover,
        &.active {
          color: var(--color-primary);
          border-color: var(--color-primary);

          i {
            color: var(--color-primary);
          }
        }
      }

      .new-btn {
        display: flex;
        width: 100%;
        height: 50px;
        font-size: 14px;
        color: #979ba5;
        border: 1px dashed #c4c6cc;
        border-radius: 2px;
        box-sizing: border-box;
        align-items: center;
        justify-content: center;

        .create-flag {
          margin-right: 5px;
          color: #c4c6cc;
        }
      }

      .use-guide {
        position: absolute;
        top: 50%;
        right: -29px;
        display: flex;
        width: 30px;
        font-size: 14px;
        color: #979ba5;
        justify-content: center;
        align-items: center;
        transform: translateY(-50%);
      }
    }

    .global-variable-content,
    .global-variable-new {
      @media (--small-viewports) {
        width: 160px;
      }

      @media (--medium-viewports) {
        width: 180px;
      }

      @media (--large-viewports) {
        width: 200px;
      }

      @media (--huge-viewports) {
        width: 220px;
      }
    }

    .step-mode-diff {
      cursor: default;

      &::after {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        content: "";
      }

      .global-variable-content {
        &.same {
          border-color: #c4c6cc;

          .variable-type {
            background: #979ba5;
          }
        }

        &.new {
          &::after {
            position: absolute;
            top: -6px;
            right: -6px;
            width: 28px;
            height: 14px;
            font-size: 12px;
            line-height: 14px;
            color: #fff;
            text-align: center;
            background: #ffa86e;
            content: "new";
          }
        }

        &.new,
        &.different {
          position: relative;
          border-color: #f9c9a9;

          .variable-type {
            background: #f5c09e;
          }
        }

        &.delete {
          border-color: #dcdee5;

          .variable-type {
            background: #dcdee5;
          }

          .variable-info {
            .variable-name,
            .variable-description {
              color: #c4c6cc;
              text-decoration: line-through;
            }
          }
        }
      }
    }
  }
</style>
